"""
    bwdata_crud.py
    ~~~~~~~~
    

    :author: Fufu, 2024/4/24
"""
from datetime import datetime
from typing import List

from fastapi_async_sqlalchemy import db
from sqlmodel import select, desc

from app.crud.base_crud import CRUDBase
from app.models import BaseBWDataModel, get_bw_data_model
from app.schemas.admin_schemas.bwdata_schema import BWDataStats
from app.utils.common_helper import get_95th, get_e95th_daily, get_e95th, get_round


class CRUDBWData(CRUDBase[BaseBWDataModel]):

    async def get_bw_stats(
            self,
            *,
            dateline: datetime,
            start_time: datetime,
            end_time: datetime,
            company_id: int,
            vendor_id: int,
            line_id: int,
    ) -> BWDataStats:
        """获取带宽统计数据(月): 传统 95, 增强 95, 月峰值, 总流量等"""
        bw_data_model = self.model
        stmt = select(bw_data_model).where(
            bw_data_model.timeline >= start_time,
            bw_data_model.timeline < end_time,
            bw_data_model.company_id == company_id,
            bw_data_model.vendor_id == vendor_id,
            bw_data_model.line_id == line_id,
        )
        res = await db.session.execute(stmt)
        datas = res.scalars().all()

        bw_stats = BWDataStats()
        bw_total_out = 0
        bw_e95_daily_datas, bw_95_datas = [], []
        day_datas = {}
        for data in datas:
            # 将数据整理为 日期 为 键, in / out / max 为 子键 的数据集
            # {"2024-04-28": {"in": [1,6,3], "out": [6,3,6], "max": [6,6,6]}...}
            day = data.timeline.strftime('%Y-%m-%d')
            if day in day_datas:
                day_datas[day]['in'].append(data.bw_in)
                day_datas[day]['out'].append(data.bw_out)
                day_datas[day]['max'].append(data.bw_max)
            else:
                day_datas[day] = {'in': [data.bw_in], 'out': [data.bw_out], 'max': [data.bw_max]}

        dt = dateline.strftime('%Y-%m-%d')
        for day, item in day_datas.items():
            # 传统 95 数据集
            bw_95_datas += item['max']
            # 增强 95 日数据列表
            bw_e95_daily_datas.append(get_e95th_daily(item['max']))
            # 总带宽(流出)
            bw_total_out += sum(item['out'])
            # 峰值带宽
            bw_stats.bw_peak_in = max(bw_stats.bw_peak_in, max(item['in']))
            bw_stats.bw_peak_out = max(bw_stats.bw_peak_out, max(item['out']))
            # 数据日期的日峰值带宽
            if day == dt:
                bw_stats.bw_peak_day = max(item['max'])

        # 传统 95 in / out
        bw_stats.bw_95 = get_95th(bw_95_datas)
        # 增强 95
        bw_stats.bw_e95 = get_e95th(bw_e95_daily_datas)
        # 总流量, 流出总带宽最大值 转换为 GBytes (带宽数据单位为: mbps, 时间刻度为: 5 分钟)
        bw_stats.total_traffic = get_round(bw_total_out * 1000 * 1000 * 300 / 8 / 1024 / 1024 / 1024)
        return bw_stats

    async def get_newest_data(self) -> BaseBWDataModel | None:
        """获取最新一条数据"""
        stmt = select(self.model).order_by(desc(self.model.timeline)).limit(1)
        res = await db.session.execute(stmt)
        return res.scalars().first()

    async def bulk_insert(self, datas: List[BaseBWDataModel]) -> bool:
        """批量插入带宽明细数据"""
        if not isinstance(datas, list) or not datas:
            return False

        db.session.add_all(datas)
        return True

    async def insert_placeholder(self, dt: datetime):
        """写入时间点占位数据"""
        db.session.add(self.model(timeline=dt))
